//------------------------------------------------------------
//  Filename: can_mac_layer.sv
//   
//  Author  : wlduan@gmail.com
//  Revise  : 2020-05-31 16:39
//  Description: 
//   
//  Copyright (C) 2014, YRBD, Inc. 					      
//  All Rights Reserved.                                       
//-------------------------------------------------------------
//
`timescale 1ns/1ps
 
module can_mac_layer ( 
    input logic clk,  
    input logic rst ,

    input logic sampled_bit,
    input logic sample_point
);      
/* Rx state machine */
logic         go_rx_idle;
logic         go_rx_id1;
logic         go_rx_rtr1;
logic         go_rx_ide;
logic         go_rx_id2;
logic         go_rx_rtr2;
logic         go_rx_r1;
logic         go_rx_r0;
logic         go_rx_dlc;
logic         go_rx_data;
logic         go_rx_crc;
logic         go_rx_crc_lim;
logic         go_rx_ack;
logic         go_rx_ack_lim;
logic         go_rx_eof;
logic         go_rx_inter;
logic         rx_idle;
logic         rx_id1;
logic         rx_rtr1;
logic         rx_ide;
logic         rx_id2;
logic         rx_rtr2;
logic         rx_r1;
logic         rx_r0;
logic         rx_dlc;
logic         rx_data;
logic         rx_crc;
logic         rx_crc_lim;
logic         rx_ack;
logic         rx_ack_lim;
logic         rx_eof;
logic         rx_inter;

logic         bus_free;
//RX state
assign go_rx_idle     =                   sample_point &  sampled_bit & last_bit_of_inter | bus_free & (~node_bus_off);
assign go_rx_id1      =                   sample_point &  (~sampled_bit) & (rx_idle | last_bit_of_inter);
assign go_rx_rtr1     = (~bit_de_stuff) & sample_point &  rx_id1  & (bit_cnt[3:0] == 4'd10);
assign go_rx_ide      = (~bit_de_stuff) & sample_point &  rx_rtr1;
assign go_rx_id2      = (~bit_de_stuff) & sample_point &  rx_ide  &   sampled_bit;
assign go_rx_rtr2     = (~bit_de_stuff) & sample_point &  rx_id2  & (bit_cnt[4:0] == 5'd17);
assign go_rx_r1       = (~bit_de_stuff) & sample_point &  rx_rtr2;
assign go_rx_r0       = (~bit_de_stuff) & sample_point & (rx_ide  & (~sampled_bit) | rx_r1);
assign go_rx_dlc      = (~bit_de_stuff) & sample_point &  rx_r0;
assign go_rx_data     = (~bit_de_stuff) & sample_point &  rx_dlc  & (bit_cnt[1:0] == 2'd3) &  (sampled_bit   |   (|data_len[2:0])) & (~remote_rq);
assign go_rx_crc      = (~bit_de_stuff) & sample_point & (rx_dlc  & (bit_cnt[1:0] == 2'd3) & ((~sampled_bit) & (~(|data_len[2:0])) | remote_rq) |
                                                          rx_data & (bit_cnt[5:0] == ((limited_data_len<<3) - 1'b1)));  // overflow works ok at max value (8<<3 = 64 = 0). 0-1 = 6'h3f
assign go_rx_crc_lim  = (~bit_de_stuff) & sample_point &  rx_crc  & (bit_cnt[3:0] == 4'd14);
assign go_rx_ack      = (~bit_de_stuff) & sample_point &  rx_crc_lim;
assign go_rx_ack_lim  =                   sample_point &  rx_ack;
assign go_rx_eof      =                   sample_point &  rx_ack_lim;
assign go_rx_inter    =                 ((sample_point &  rx_eof  & (eof_cnt == 3'd6)) | error_frame_ended | overload_frame_ended) & (~overload_request);
assign go_error_frame = (form_err | stuff_err | bit_err | ack_err | (crc_err & go_rx_eof));

assign error_frame_ended    = (error_cnt2 == 3'd7) & tx_point;
assign overload_frame_ended = (overload_cnt2 == 3'd7) & tx_point;
assign go_overload_frame = (     sample_point & ((~sampled_bit) | overload_request) & (rx_eof & (~transmitter) & (eof_cnt == 3'd6) | error_frame_ended | overload_frame_ended) | 
                                 sample_point & (~sampled_bit) & rx_inter & (bit_cnt[1:0] < 2'd2) |
                                 sample_point & (~sampled_bit) & ((error_cnt2 == 3'd7) | (overload_cnt2 == 3'd7))
                           )  & (~overload_frame_blocked)  ;

assign go_crc_enable  = hard_sync | go_tx;
assign rst_crc_enable = go_rx_crc;
//state machine
always @ (posedge clk or posedge rst) begin
  if (rst) begin
   {rx_idle,rx_id1,rx_rtr1,rx_ide,rx_id2,rx_rtr2,rx_r1,rx_r0,rx_dlc,rx_data,rx_crc,rx_crc_lim,rx_ack,rx_ack_lim,rx_eof,rx_inter} <= 'b0;
  end
  else if(go_error_frame)begin
   {rx_idle,rx_id1,rx_rtr1,rx_ide,rx_id2,rx_rtr2,rx_r1,rx_r0,rx_dlc,rx_data,rx_crc,rx_crc_lim,rx_ack,rx_ack_lim,rx_eof,rx_inter} <= 'b0;
  end
  else begin
    rx_idle    <=  ( go_rx_id1                                  )  ?  ( 1'b0 : ( ( go_rx_idle    ) ?  1'b1 : rx_idle    ) ); 
    rx_id1     <=  ( go_rx_rtr1                                 )  ?  ( 1'b0 : ( ( go_rx_id1     ) ?  1'b1 : rx_id1     ) ); 
    rx_rtr1    <=  ( go_rx_ide                                  )  ?  ( 1'b0 : ( ( go_rx_rtr1    ) ?  1'b1 : rx_rtr1    ) ); 
    rx_ide     <=  ( go_rx_r0 | go_rx_id2                       )  ?  ( 1'b0 : ( ( go_rx_ide     ) ?  1'b1 : rx_ide     ) ); 
    rx_id2     <=  ( go_rx_rtr2                                 )  ?  ( 1'b0 : ( ( go_rx_id2     ) ?  1'b1 : rx_id2     ) ); 
    rx_rtr2    <=  ( go_rx_r1                                   )  ?  ( 1'b0 : ( ( go_rx_rtr2    ) ?  1'b1 : rx_rtr2    ) ); 
    rx_r1      <=  ( go_rx_r0                                   )  ?  ( 1'b0 : ( ( go_rx_r1      ) ?  1'b1 : rx_r1      ) ); 
    rx_r0      <=  ( go_rx_dlc                                  )  ?  ( 1'b0 : ( ( go_rx_r0      ) ?  1'b1 : rx_r0      ) ); 
    rx_dlc     <=  ( go_rx_data | go_rx_crc                     )  ?  ( 1'b0 : ( ( go_rx_dlc     ) ?  1'b1 : rx_dlc     ) ); 
    rx_data    <=  ( go_rx_crc                                  )  ?  ( 1'b0 : ( ( go_rx_data    ) ?  1'b1 : rx_data    ) ); 
    rx_crc     <=  ( go_rx_crc_lim                              )  ?  ( 1'b0 : ( ( go_rx_crc     ) ?  1'b1 : rx_crc     ) ); 
    rx_crc_lim <=  ( go_rx_ack                                  )  ?  ( 1'b0 : ( ( go_rx_crc_lim ) ?  1'b1 : rx_crc_lim ) ); 
    rx_ack     <=  ( go_rx_ack_lim                              )  ?  ( 1'b0 : ( ( go_rx_ack     ) ?  1'b1 : rx_ack     ) ); 
    rx_ack_lim <=  ( go_rx_eof                                  )  ?  ( 1'b0 : ( ( go_rx_ack_lim ) ?  1'b1 : rx_ack_lim ) ); 
    rx_eof     <=  ( go_rx_inter  | go_overload_frame           )  ?  ( 1'b0 : ( ( go_rx_eof     ) ?  1'b1 : rx_eof     ) ); 
    rx_inter   <=  ( go_rx_idle | go_rx_id1 | go_overload_frame )  ?  ( 1'b0 : ( ( go_rx_inter   ) ?  1'b1 : rx_inter   ) ); 
  end
end
// ID register
always @ (posedge clk or posedge rst) begin
  if (rst) begin
    id   <= 29'h0;
    rtr1 <= 1'b0;
    rtr2 <= 1'b0;
    ide  <= 1'b0;
    data_len <= 4'b0;
    tmp_data <= 8'h0;
    crc_in   <= 15'h0;
  end
  else begin
    id   <= (sample_point & (rx_id1 | rx_id2) & (~bit_de_stuff)) ? {id[27:0], sampled_bit}      : id       ;
    rtr1 <= (sample_point & rx_rtr1 & (~bit_de_stuff))           ? sampled_bit                  : rtr1     ;
    rtr2 <= (sample_point & rx_rtr2 & (~bit_de_stuff))           ? sampled_bit                  : rtr2     ;
    ide  <= (sample_point & rx_ide & (~bit_de_stuff))            ? sampled_bit                  : ide      ;
    data_len <= (sample_point & rx_dlc & (~bit_de_stuff))        ? {data_len[2:0], sampled_bit} : data_len ;
    tmp_data <= (sample_point & rx_data & (~bit_de_stuff))       ? {tmp_data[6:0], sampled_bit} : tmp_data ;
    crc_in   <= (sample_point & rx_crc & (~bit_de_stuff))        ? {crc_in[13:0], sampled_bit}  : crc_in   ;
  end
end
// bit_cnt
always @ (posedge clk or posedge rst) begin
  if (rst)
    bit_cnt <= 6'd0;
  else if (go_rx_id1 | go_rx_id2 | go_rx_dlc | go_rx_data | go_rx_crc | go_rx_ack | go_rx_eof | go_rx_inter | go_error_frame | go_overload_frame)
    bit_cnt <= 6'd0;
  else if (sample_point & (~bit_de_stuff))
    bit_cnt <= bit_cnt + 1'b1;
end

logic   [3:0] bus_free_cnt;
logic         bus_free_cnt_en;
logic         waiting_for_bus_free;

always @ (posedge clk or posedge rst) begin
  if (rst)
    bus_free_cnt <= 4'h0;
  else if (sample_point) begin
      if (sampled_bit & bus_free_cnt_en & (bus_free_cnt < 4'd10))
        bus_free_cnt <= bus_free_cnt + 1'b1;
      else
        bus_free_cnt <= 4'h0;
    end
end


always @ (posedge clk or posedge rst) begin
  if (rst)
    bus_free_cnt_en <= 1'b0;
  else if ((~reset_mode) & reset_mode_q | node_bus_off_q & (~reset_mode))
    bus_free_cnt_en <= 1'b1;
  else if (sample_point & sampled_bit & (bus_free_cnt==4'd10) & (~node_bus_off))
    bus_free_cnt_en <= 1'b0;
end


always @ (posedge clk or posedge rst) begin
  if (rst)
    bus_free <= 1'b0;
  else if (sample_point & sampled_bit & (bus_free_cnt==4'd10) && waiting_for_bus_free)
    bus_free <= 1'b1;
  else
    bus_free <= 1'b0;
end


always @ (posedge clk or posedge rst) begin
  if (rst)
    waiting_for_bus_free <= 1'b1;
  else if (bus_free & (~node_bus_off))
    waiting_for_bus_free <= 1'b0;
  else if (node_bus_off_q & (~reset_mode))
    waiting_for_bus_free <= 1'b1;
end
      
endmodule
